type LoopTaskManagerDispatcher = (m: LoopTaskManager) => any
type LoopTaskManagerTrigger = LoopTaskManagerDispatcher | { dispatcher: LoopTaskManagerDispatcher };
interface LoopTaskManagerOptions {
    inter?: number;
}

/*

    class TestTask {
        dispatcher(task: LoopTaskManager) {
            console.log('test');
        }
    }


    const ttTask = new TestTask();
    const ccTask2 = new LoopTaskManager(ttTask);
    const ccTask1 = new LoopTaskManager(async (task: any) => {
        console.log('test');
    });

    // 使用函数式调度器
    const task = createLoopTakManager((manager) => {
    console.log('Task executed');
    // 模拟异步操作
    return new Promise(resolve => {
        setTimeout(() => {
        manager.idle(); // 标记任务完成
        resolve();
        }, 500);
    });
    }, { inter: 2000 });

    // 开始执行
    task.next();

    // 5秒后销毁
    setTimeout(() => task.destroy(), 5000);

 */

class LoopTaskManager {
    busy = false;
    timer: any = -1;
    destroyed = false;
    key = Math.random();

    constructor(
        public dispatcher: LoopTaskManagerTrigger,
        public options: LoopTaskManagerOptions = {},
    ) {
        this.next = this.next.bind(this);
        this.asyncNext = this.asyncNext.bind(this);
        this.forceNext = this.forceNext.bind(this);
    }

    idle() {
        this.busy = false;
    }

    forceNext() {
        this.idle();
        this.next();
    }

    next() {
        if (this.destroyed) return;
        if (this.busy) return;

        this.busy = true;
        const context: any = this.dispatcher;
        const dispatcher = context?.dispatcher || context;

        Promise.resolve(dispatcher.call(context, this)).catch((err) => {
            this.asyncNext();
            return Promise.reject(err);
        });
    }

    asyncNext(inter?: number) {
        clearTimeout(this.timer);
        this.timer = setTimeout(this.next, inter || this.options?.inter || 1e3);
    }

    destroy() {
        this.destroyed = true;
        clearTimeout(this.timer);
        console.log('[destroy loop task]', this.key);
    }
}

export function createLoopTakManager(dispatcher: LoopTaskManagerTrigger, options?: LoopTaskManagerOptions) {
    return new LoopTaskManager(dispatcher, options);
}
